﻿/*
 * UIntArrayTag
 * 
 * initial implementation : 5.12.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;


namespace Petra.Gis.ImagingServices.Tiff
{
  /// <summary>
  /// represents special tag that holds many of values in List<int>
  /// </summary>
  public class UIntArrayTag : TagBase
  {


    ///<summary>
    /// Creates a new tag from input binary stream
    /// The additional data is somewhere in the TIFF file.
    /// The current position will be stored, the method can seek to the offset
    /// position and load the data.
    ///</summary>
    public UIntArrayTag(TiffReader tiffReader)
      : base()
    {
      // init array
      _tagData = new List<uint>();
      _tagNumber = (int)tiffReader.ReadUInt16();

      try { _tagId = (TagType)_tagNumber; }
      catch { _tagId = TagType.UNKNOWN; }

      if (!(_tagId == TagType.STRIPBYTECOUNTS || 
            _tagId == TagType.TILEBYTECOUNTS ||
            _tagId == TagType.TILEOFFSETS ||
            _tagId == TagType.STRIPOFFSETS))
        throw new ArgumentException("special tag cant be created for id = " + _tagId.ToString());


      _type = (TagDataType)tiffReader.ReadInt16();
      _count = tiffReader.ReadInt32();

      if (_count < 1)
        throw new InvalidFileStructureException("Invalid count value for tag " + _tagId.ToString() + " (" + _count.ToString()+ ").");

      if (!(_type == TagDataType.LONG ||
            _type == TagDataType.SHORT))
        throw new InvalidFileStructureException("Invalid data type value for tag " + _tagId.ToString() + " (" + _count.ToString() + ").");

      prepareTagData(tiffReader);


    }





    protected List<uint> _tagData;

    protected override IList tifTagData
    {
      get { return this.TagData; }
      set { this.TagData = (List<uint>)value; }
    }


    new public List<uint> TagData
    {
      get { return _tagData; }
      set 
      {
        if (value != null)
          throw new ArgumentException("tag data null");

        _tagData = value; 
      }
    }




    protected void prepareTagData(TiffReader tiffReader)
    {
      _offset = tiffReader.ReadInt32();

      if (dataOustideIfd(_type, _count)) //if data outside of table, read them into vector
      {
        tiffReader.BaseStream.Seek(_offset, SeekOrigin.Begin);

        for (int i = 0; i < _count; i++)
        {
          switch (_type)
          {
            case TagDataType.BYTE:
            case TagDataType.SBYTE:
              _tagData.Add(tiffReader.ReadByte()); //no endian conversion necessary for byte ;-)
              break;
            //case TagDataType.ASCII:
            //  //sb.Append(tiffReader.ReadChar());//readString(count); //no endian conversion necessary for byte ;-)
            //  strArr[i] = tiffReader.ReadByte();
            //  break;
            case TagDataType.SHORT:
              _tagData.Add(tiffReader.ReadUInt16());
              break;
            //case TagDataType.SSHORT:
            //  _tagData.Add(tiffReader.ReadInt16());
            //  break;
            case TagDataType.LONG:
              _tagData.Add(tiffReader.ReadUInt32());
              break;
            //case TagDataType.SLONG:
            //  _tagData.Add(tiffReader.ReadInt32());
            //  break;
            //case TagDataType.DOUBLE:
            //  _tagData.Add(tiffReader.ReadDouble());
            //  break;
            //case TagDataType.FLOAT:
            //  _tagData.Add(tiffReader.ReadSingle());
            //  break;
            //case TagDataType.RATIONAL:
            //  _tagData.Add(new Rational(tiffReader.ReadInt32(),
            //                          tiffReader.ReadInt32()));
            //  break;
          }
        }
        // revert offset for next tag ??
        //tiffReader.BaseStream.Seek(oldOffset, SeekOrigin.Begin);
        // buid string
        //if (type == TagDataType.ASCII)
        //  //  vector.Add(sb.ToString());
        //  vector.Add(System.Text.ASCIIEncoding.ASCII.GetString(strArr));
      }
      else
      {
        //if (type == TagDataType.ASCII)
        //  vector.Add(System.Text.ASCIIEncoding.ASCII.GetString(BitConverter.GetBytes(offset)));
        //else
          _tagData.Add((uint)_offset);
      }



      
    }

  }
}
